﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace ThatsMeSDK.Core.Filter
{
    class HtmlFilter
    {
        //Private Vars
        private Regex regHTML;
		private Regex regUML;
		private Regex regBB;
        private HtmlSpecialCharachters specialChars;
		
        /// <summary>
        /// Original Html String
        /// </summary>
		public string HtmlString{get; private set;}

        /// <summary>
        /// Filtered String
        /// </summary>
		public string FilteredString{get; private set;}

        /// <summary>
        /// Creates a new HtmlFilter
        /// </summary>
        public HtmlFilter()
		{
			regHTML = new Regex("</?\\w+((\\s+\\w+(\\s*=\\s*(?:\".*?\"|'.*?'|[^'\">\\s]+))?)+\\s*|\\s*)/?>", RegexOptions.None);
			regUML = new Regex("&(?<uml>([A-Za-z]{1,100}));", RegexOptions.None);
			regBB = new Regex(@"\[[\w\s_\./=:\?]*\]", RegexOptions.None);
            specialChars = new HtmlSpecialCharachters();
		}

        /// <summary>
        /// Filters a html string for html and umlaut tags
        /// </summary>
        /// <param name="html">Html input string</param>
        /// <returns>Returns a string without Html</returns>
        public string Filter(string html)
		{
			string tempString = "";
            HtmlString = html;
			
			//Filter UmlTags 
			tempString = FilterUmlauts(html);
			
			//Filter BBTags
            tempString = FilterBBTags(tempString);

            //Filter HTmlTags
            //tempString = FilterHtmlTags(tempString); //Slower but better to customize
            tempString = regHTML.Replace(tempString, ""); //Simple and faster version

			return tempString;
		}
		
        /// <summary>
        /// Checks for umlauts tags and replaces them through the specified char
        /// </summary>
        /// <param name="html">html insert</param>
        /// <returns>Filered string</returns>
		private string FilterUmlauts(string html)
		{
			int offset = 0;

            //Check for matches
			MatchCollection matches = regUML.Matches(html);
			
            //iterate trough matches and replace them
			foreach(Match umlMatch in matches)
			{
                //get index
                int chrIndex = 0;
                specialChars.HtmlSpecialChars.TryGetValue(umlMatch.Groups["uml"].Value, out chrIndex);

                //Check if index is out of bound (OFB)
                if (chrIndex > -1)
                {
                    //convert to char and replace
                    string umlChar = char.ConvertFromUtf32(chrIndex);
                    html = html.Remove(umlMatch.Index - offset, umlMatch.Length);
                    html = html.Insert(umlMatch.Index - offset, umlChar);

                    //Set offset because of iteration
                    offset += umlMatch.Length - umlChar.Length;
                }
			}
			
			return html;
		}

        /// <summary>
        /// Check for html tags and replaces them
        /// </summary>
        /// <param name="html">html insert</param>
        /// <returns>filtered string</returns>
        private string FilterHtmlTags(string html)
        {
            int offset = 0;

            //Check for matches
            MatchCollection matches = regHTML.Matches(html);

            //iterate trough matches and replace them
            foreach (Match htmlMatch in matches)
            {
                string newChar = "";

                html = html.Remove(htmlMatch.Index - offset, htmlMatch.Length);
                html = html.Insert(htmlMatch.Index - offset, newChar);

                    //Set offset because of iteration
                offset += htmlMatch.Length - newChar.Length;
            }

            return html;
        }
        
        /// <summary>
        /// Check for bb tags and replaces them
        /// </summary>
        /// <param name="html">html insert</param>
        /// <returns>filtered string</returns>
        private string FilterBBTags(string html)
        {
        	int offset = 0;
        	
        	//Check for matches
        	MatchCollection matches = regBB.Matches(html);
        	
        	//iterate through matches and replace them
        	foreach (Match bbMatch in matches)
        	{
        		string newChar = "";

                html = html.Remove(bbMatch.Index - offset, bbMatch.Length);
                html = html.Insert(bbMatch.Index - offset, newChar);

                //Set offset because of iteration
                offset += bbMatch.Length - newChar.Length;
        	}
        	
        	return html;
        }
    }
}
